import org.junit.Test;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Scanner;

/**
 * @program: nio-learning
 * @description: 非阻塞式nio
 * @author: zhaoxianglong
 * @create: 2021-03-10 17:19
 **/
public class NoBlockingNioTest {

    /**
     * 服务端
     * @throws IOException io异常
     */
    @Test
    public void server() throws IOException {

        //创建通道
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        //设置通道非阻塞
        serverSocketChannel.configureBlocking(false);

        //注册端口
        serverSocketChannel.bind(new InetSocketAddress(8080));

        //创建选择器
        Selector selector = Selector.open();

        //将通道注册进选择器
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        //循环 选择器中通道数大于0? 进入循环 : 跳过
        while (selector.select() > 0) {

            //遍历选择其中所有通道
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();


            while (iterator.hasNext()) {
                //获取连接
                SelectionKey selectionKey = iterator.next();

                //判断连接类型
                if (selectionKey.isAcceptable()) {

                    //获取通道
                    SocketChannel socketChannel = serverSocketChannel.accept();

                    //通道非阻塞
                    socketChannel.configureBlocking(false);

                    //注册到选择器
                    socketChannel.register(selector, SelectionKey.OP_READ);
                } else if (selectionKey.isReadable()) {
                    //获取通道
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();

                    //创建缓冲区
                    ByteBuffer allocate = ByteBuffer.allocate(1024);

                    //读取数据
                    int len;
                    if ((len = socketChannel.read(allocate)) > 0) {
                        allocate.flip();
                        System.out.println(new String(allocate.array(), 0, len));
                        allocate.clear();
                    }
                }

                //删除连接
                iterator.remove();
            }
        }
    }

    /**
     * 客户端
     * @throws IOException io异常
     *   注: 如此方法下控制台输入不能输入 , 需设置vm参数 : -Deditable.java.test.console=true
     */
    @Test
    public void client() throws IOException {

        //创建通道
        SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1" , 8080));

        //设定非阻塞
        socketChannel.configureBlocking(false);

        //创建缓冲区
        ByteBuffer allocate = ByteBuffer.allocate(1024);

        Scanner scanner = new Scanner(System.in);

        while (scanner.hasNext()){
            allocate.put(scanner.next().getBytes());
            allocate.flip();
            socketChannel.write(allocate);
            allocate.clear();
        }
    }

}
